use crate::core::error::AppError;
use openssl::{pkey::PKey, sign::Signer, hash::MessageDigest};
use std::path::Path;

pub fn sign_directory(dir: &Path, private_key: &Path) -> Result<(), AppError> {
    let key = std::fs::read(private_key)?;
    let pkey = PKey::private_key_from_pem(&key)?;
    let mut signer = Signer::new(MessageDigest::sha256(), &pkey)?;
    
    // 遍历目录计算哈希
    for entry in walkdir::WalkDir::new(dir)
        .sort_by(|a,b| a.path().cmp(b.path()))
    {
        let entry = entry?;
        if entry.file_type().is_file() {
            let data = std::fs::read(entry.path())?;
            signer.update(&data)?;
        }
    }
    
    // 生成签名
    let signature = signer.sign_to_vec()?;
    std::fs::write(dir.join(".signature"), signature)?;
    Ok(())
}

pub fn verify_directory_signature(dir: &Path, public_key: &Path) -> Result<(), AppError> {
    let signature = std::fs::read(dir.join(".signature"))?;
    let key = std::fs::read(public_key)?;
    let pkey = PKey::public_key_from_pem(&key)?;
    let mut verifier = openssl::sign::Verifier::new(MessageDigest::sha256(), &pkey)?;
    
    // 重新计算目录哈希
    for entry in walkdir::WalkDir::new(dir)
        .sort_by(|a,b| a.path().cmp(b.path()))
    {
        let entry = entry?;
        if entry.file_type().is_file() && entry.file_name() != ".signature" {
            let data = std::fs::read(entry.path())?;
            verifier.update(&data)?;
        }
    }
    
    if !verifier.verify(&signature)? {
        return Err(AppError::SecurityError("目录签名验证失败".into()));
    }
    Ok(())
}